//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CTechnique9.cpp>
///	@path	~/src/graphics/dx9/
///	@date	2007/11/20
///	@desc	Technique implementation in DX9.

#include "config/config.h"

#include "lib/system/thread_debug.h"

#include "graphics/DxHelpers.h"
#include "graphics/IGeometry.h"
#include "graphics/dx9/CTechnique9.h"

namespace xeres {

	IMPL_IOBJECT_CLASS( CTechnique9 );

	// ctor
	CTechnique9::CTechnique9( RefWeak<IEffect> effect , D3DXHANDLE technique )
		: m_effect( effect )
		, m_pTechnique( technique )
	{
		// get effect
		IUnknown * pEffect = effect->GetEffectInterface();
		HRESULT hr = pEffect->QueryInterface( IID_ID3DXEffect , (void**)&m_pEffect );
		XS_ASSERT( SUCCEEDED(hr) );
		pEffect->Release();

		// get description
		hr = m_pEffect->GetTechniqueDesc( m_pTechnique , &m_desc );
		XS_ASSERT( SUCCEEDED(hr) );

		// convert name
		mbs_to_wcs( AString( m_desc.Name ) , m_name );
	}

	// dtor
	CTechnique9::~CTechnique9( void )
	{
		// clear cache if needed
		m_effect->UnusedTechnique( this );
		m_effect = NULL;
	}

	// GetVariableCount
	size_t CTechnique9::GetVariableCount( void )
	{
		return m_effect->GetVariableCount();
	}
	// GetVariableByIndex
	RefPass< IShaderVariable > CTechnique9::GetVariableByIndex( size_t index )
	{
		return m_effect->GetVariableByIndex( index );
	}
	// GetVariableByName
	RefPass< IShaderVariable > CTechnique9::GetVariableByName( const AString& name )
	{
		return m_effect->GetVariableByName( name );
	}
	// GetVariableBySemantic
	RefPass< IShaderVariable > CTechnique9::GetVariableBySemantic( const AString& semantic )
	{
		return m_effect->GetVariableBySemantic( semantic );
	}

	// get technique name
	const WString& CTechnique9::GetName( void )
	{
		return m_name;
	}

	// get pass count
	size_t CTechnique9::GetPassCount( void )
	{
		return m_desc.Passes;
	}
	// GetEffect
	RefWeak<IEffect> CTechnique9::GetEffect( void )
	{
		return m_effect;
	}

	// Begin
	void CTechnique9::Begin( uint pass , RenderContext& rc )
	{
		XS_ASSERT( pass < m_desc.Passes );
		if( pass == 0 )
		{
			UINT total = 0;
			m_pEffect->SetTechnique( m_pTechnique );
			m_pEffect->Begin( &total , 0 );
			m_pEffect->BeginPass( 0 );
			XS_ASSERT( total == m_desc.Passes );
		}
		else
		{
			m_pEffect->BeginPass( pass );
		}
	}

	// End
	void CTechnique9::End( uint& pass , RenderContext& rc )
	{
		m_pEffect->EndPass();
		++pass;
		if( pass >= m_desc.Passes )
		{
			m_pEffect->End();
			pass = 0;
		}
	}
	// Draw
	void CTechnique9::Draw( RenderContext& rc , RefWeak<IGeometry> geometry )
	{
		geometry->EstablishBuffer( rc );
		UINT total = 0;
		m_pEffect->SetTechnique( m_pTechnique );
		m_pEffect->Begin( &total , 0 );
		for( UINT i = 0 ; i < total ; ++i )
		{
			m_pEffect->BeginPass( i );
			geometry->Draw( rc );
			m_pEffect->EndPass();
		}
		m_pEffect->End();
	}

} // namespace xeres
